/*
 * strclithread2.c
 *
 *  Created on: Apr 29, 2012
 *      Author: root
 */
#include    "unpthread.h"
#include    "files.h"
#include     "readBuffer.h"

char user_part(char *buf);
char who_part(char *buf);
char quit_part(char *buf);
void help_part();
char message_req(char *buf, char *mid, char *yid);
int debug_part(int toggle);
char file_transfer_part(char *buf, char *fn, char *send, char *mid);
void print_request(char * request);
void debug_request(char *request);
void debug_response(char *response);
void print_response(char *response);
void print_response2(char *response, char *w1, char *w5);

void *FILE_TRANSFER(void *arg);
void *client_stdin(void *);
void create_ft(char *ip, char *port, char *file_name);
static void *do_filetransfer(void *arg);

static int sockfd;
static FILE *fp;
static int done;
int talk_bit = 0;
char myid[100];

Client *file;

pthread_mutex_t ft_mutex = PTHREAD_MUTEX_INITIALIZER;

int send_bit = 0;
int dup_file = 1;
int toggle = 0;
int file_distinct = 1;

void str_cli(FILE *fp_arg, int sockfd_arg) {

    char w1[100], w2[100], w3[100], w4[100], w5[100], w6[100], w7[100], w8[100],
            w9[100], w10[100];

    pthread_t tid;
    pthread_t tid1;
    ssize_t n;

    sockfd = sockfd_arg; /* copy arguments to externals */
    fp = fp_arg;

    ReadBuffer *rbuf;
    rbuf = createRbuf(MAXLINE);
    char response[MAXLINE];
    char response1[MAXLINE];

    Pthread_create(&tid, NULL, client_stdin, NULL); // input thread
    Pthread_create(&tid1, NULL, FILE_TRANSFER, "9000"); // FILE_TRANSFET thread
    for (;;) {
        if ((n = readBuf(rbuf, sockfd)) < 0)
            err_sys("read error");

        if (n == 0)
            break;

        while (getMessage(rbuf, response, MAXLINE) != NULL) {
            strcpy(response1, response);

            n = sscanf(response, "%s %s %s %s %s %s %s %s %s %s", w1, w2, w3,
                    w4, w5, w6, w7, w8, w9, w10);
            printf("\n");

            if (toggle == 0)
                print_response2(response, w1, w5);

            if (toggle == 1)
                debug_response(response);

            if (!strcmp(w1, "298")) {
                pthread_mutex_lock(&ft_mutex);
                sleep(1); // for divide many file transfer request
                file = createClient(file_distinct);
                file_distinct++;
                n = sscanf(response1, "%s %s %s %s %s %s %s %s %s %s", w1, w2,
                        w3, w4, w5, w6, w7, w8, w9, w10);
                sprintf(file->from, "%s FROM %s TO %s\r\n\r\n", w6, w8, w10);
                strcpy(file->user, w6);
                printf("%s file transfer y/n ????\n", w6);
                send_bit = 1;

            }
            //227 response recv, connect with receiver
            if (!strcmp(w1, "227")) {
                create_ft(w2, "9000", w8);
            }

            if (talk_bit == 1) {
                printf("%s > ", myid);
                fflush(stdout);
            }

            if (talk_bit == 0) {
                printf(">>");
                fflush(stdout);
                fflush(stderr);
            }
            memset(response, 0, strlen(response));
        }
    }

    if (done == 0)
        err_quit("server terminated prematurely");
}
//program start, wait accept(connect client(sender))  ,
void *
FILE_TRANSFER(void *arg) {
    int listenfd, *iptr;
    pthread_t tid2;

    char *port;

    port = arg;
    socklen_t addrlen, len;
    struct sockaddr *cliaddr;

    listenfd = Tcp_listen(NULL, port, &addrlen);
    cliaddr = Malloc(addrlen);

    for (;;) {

        len = addrlen;
        iptr = Malloc(sizeof(int));
        *iptr = accept(listenfd, cliaddr, &len);
        Pthread_create(&tid2, NULL, &do_filetransfer, iptr);
    }
    return (NULL);
}

//connect and recv file
static void *
do_filetransfer(void *arg) {
    int connfd, n;
    char buf[MAXLINE];
    connfd = *((int *) arg);

    Pthread_detach(pthread_self());
    printf("create %d \n", connfd);
    printf("\n------------start file transfer------------\n");
    while ((n = read(connfd, buf, MAXLINE)) > 0) {
        printf("file length is a %d\n", n);
        printf("file name is %s\n", file->user);

        FILE *fp = fopen(file->user, "rb");
        if (fp == NULL) {
            printf("Not exist file!!!!!!!!!!!!!!!!\n");

            FILE *fp = fopen(file->user, "wt");
            fwrite(buf, 1, n, fp);

            memset(buf, 0, strlen(buf));
            fclose(fp);
        } else {
            printf("Exist file!!!!!!!!!!!!!!!!!!!!!\n");
            fclose(fp);

            sprintf(file->user, "%s(%d)", file->user, dup_file);
            printf("file name is %s\n", file->user);
            FILE *fp = fopen(file->user, "wt");
            fwrite(buf, 1, n, fp);
            memset(buf, 0, strlen(buf));
            fclose(fp);
        }

        printf("---------file transfer success---------\n\n\n");
        printf(">>");
        fflush(stdout);

    }
    close(connfd);
    return (NULL);
}
// create ft socket and open file and file transfer
void create_ft(char *ip, char *port, char *file_name) {

    int sesockfd;
    char buf[MAXLINE];
    char filename[100];
    int len;
    strcpy(filename, file_name);
    sesockfd = Tcp_connect(ip, port);

    printf("sock num is%d\n", sesockfd);
    printf("\n\n-----------start file transfer-----------------\n");
    FILE*fp1 = fopen(file_name, "rb");
    len = fread(buf, 1, sizeof(buf), fp1);

    printf("file length is a %d\n", len);
    printf("file name is %s\n", filename);

    Writen(sesockfd, buf, len);
    fclose(fp1);
    printf("-------------end file transfer-----------------\n\n\n");
    printf(">>");
    fflush(stdout);
}

void *
client_stdin(void *arg) {
    char response[MAXLINE];
    ssize_t n;
    int err = 0;

    char word1[100];
    char word2[100];
    char word3[100];
    char word4[100];
    char youid[100];
    char *token;
    memset(myid, 0, strlen(myid));
    printf(">>");
    fflush(stdout);
    for (;;) {
        // stdin part
        if (Fgets(response, MAXLINE, fp) != NULL) {
            if (talk_bit == 1) {
                if (!strcmp(response, ".\n")) {
                    printf(
                            "------------------close talk mode!-------------------\n");
                    printf(">>");
                    fflush(stdout);
                    talk_bit = 0;
                    err = 1;

                }
            }

            // file transfer , send_bit=1 -> only  y/n
            if (send_bit == 1) {
                if (!strcmp(response, "y\n")) {
                    pthread_mutex_unlock(&ft_mutex);
                    err = 1; // no error
                    send_bit = 0; //return command mode
                    Fputs(response, stdout);
                    sprintf(response, "ACCEPT %s", file->from);


                    if (toggle == 1)
                        debug_request(response);

                    Writen(sockfd, response, strlen(response));
                } else if (!strcmp(response, "n\n")) {
                    pthread_mutex_unlock(&ft_mutex);
                    err = 1;    //no error
                    send_bit = 0; //return command mode
                    sprintf(response, "REJECT %s", file->from);


                    if (toggle == 1)
                        debug_request(response);

                    Writen(sockfd, response, strlen(response));
                }
            }

            if (talk_bit == 0) {
                n = sscanf(response, "%s %s %s %s", word1, word2, word3, word4);

                //request user message
                if (!strcmp(word1, "user"))
                    if (n == 2) {
                        err = 1;
                        strcpy(myid, word2);
                        user_part(word2);

                        if (toggle == 1)
                            debug_request(word2);

                        Writen(sockfd, word2, strlen(word2));

                    }
                //request who message
                if (!strcmp(word1, "who"))
                    if (n == 1) {
                        err = 1;
                        who_part(word1);

                        if (toggle == 1)
                            debug_request(word1);

                        Writen(sockfd, word1, strlen(word1));

                    }
                //go talk mode
                if (!strcmp(word1, "talk"))
                    if (n == 2) {
                        strcpy(youid, word2);
                        talk_bit = 1;
                        printf(
                                "-------------------talk mode!--------------------\n");
                        printf("%s > ", myid);
                        fflush(stdout);
                        continue;
                    }
                //quit part
                if (!strcmp(word1, "quit"))
                    if (n == 1) {
                        err = 1;
                        quit_part(word1);
                        if (toggle == 1)
                            debug_request(word1);

                        Writen(sockfd, word1, strlen(word1));
                        break;

                    }
                //help part
                if (!strcmp(word1, "help"))
                    if (n == 1) {
                        err = 1;
                        help_part();
                    }
                //debug part
                if (!strcmp(word1, "debug"))
                    if (n == 1) {
                        err = 1;
                        toggle = debug_part(toggle);
                    }

                //send request message and check file existence
                if (!strcmp(word1, "send"))
                    if (n == 3) {
                        err = 1;
                        n = sscanf(response, "%s %s %s", word1, word2, word3);

                        file_transfer_part(word1, word2, word3, myid);
                        FILE *fp = fopen(word2, "rb");
                        if (fp == NULL) {
                            printf("Not exist file!!!!!!!!!!!!!!!!\n");
                            continue;
                        } else {
                            fclose(fp);
                        }

                        if (toggle == 1)
                            debug_request(word1);
                        Writen(sockfd, word1, strlen(word1));
                        send_bit = 1;
                    }

            }

            if (talk_bit == 1) { // talk mode , FROM  request
                token = strtok(response, "\n");
                strcpy(response, token);
                message_req(response, myid, youid);

                if (toggle == 1)
                    debug_request(response);

                Writen(sockfd, response, strlen(response));
                err = 1;
            }

            if (err == 0) { // for exception
                token = strtok(response, "\n");
                sprintf(response, "err\r\n\r\n");
                Writen(sockfd, response, strlen(response));
            }
            err = 0;

            memset(response, 0, strlen(response));
            memset(word1, 0, strlen(word1));
            memset(word2, 0, strlen(word2));
        }
    }
    Shutdown(sockfd, SHUT_WR); /* EOF on stdin, send FIN */

    done = 1;
    return (NULL);
    /* return (i.e., thread terminates) when end-of-file on stdin */
}

//make user request message
char user_part(char *buf) {
    char ID[100];
    strcpy(ID, buf);
    sprintf(buf, "USER %s\r\n\r\n", ID);
    return (strlen(buf));
}

//make who request message
char who_part(char *buf) {
    char who[3];
    strcpy(who, buf);
    sprintf(buf, "WHO\r\n\r\n");
    return (strlen(buf));
}

//make FROM  request message at talk mode
char message_req(char *buf, char *mid, char *yid) {
    char message[MAXLINE];
    char m_id[100];
    char y_id[100];
    strcpy(m_id, mid);
    strcpy(y_id, yid);
    strcpy(message, buf);
    sprintf(buf, "FROM %s TO %s\r\n%s\r\n\r\n", m_id, y_id, message);
    return (strlen(buf));

}

//make quit request message
char quit_part(char *buf) {
    char quit[4];
    strcpy(quit, buf);
    sprintf(buf, "QUIT\r\n\r\n");
    return (strlen(buf));
}

//command help
void help_part() {
    printf("****************************************************\n");
    printf("----User [ID(my id)]'Enter' is Log in\n");
    printf("----who'Enter' is Logged User ID list\n");
    printf("----talk [ID(your id)]'Enter' is talk mode\n");
    printf("----In the talk mode, [message] typing\n");
    printf("----In the talk mode, .'Enter'  is End of talk mode\n");
    printf("----debug'Enter' is debug mode!\n");
    printf("----quit'Enter' is Close the chatting\n");
    printf("----send [file_name] [receiver(ID)] 'Enter' is file transfer\n");
    printf("****************************************************\n");
    printf(">>");
    fflush(stdout);
}

//debug mode on or off toggle
int debug_part(int toggle) {
    if (toggle == 0) {
        printf("debug on!\n");
        toggle = 1;

    } else {
        toggle = 0;

        printf("debug off!\n");
    }
    printf(">>");
    fflush(stdout);
    return (toggle);

}
//make send message
char file_transfer_part(char *buf, char *fn, char *send, char *mid) {

    sprintf(buf, "SEND %s FROM %s TO %s\r\n\r\n", fn, mid, send);

    return (strlen(buf));
}
//display request message
void print_request(char * request) {
    char buf[MAXLINE];

    strcpy(buf, request);
    printf("---------request---------\n");
    Fputs(buf, stdout);
    printf("-------------------------\n");

}
//display debug request message
void debug_request(char *request) {
    char buf[MAXLINE];
    strcpy(buf, request);
    fprintf(stderr, "--------debug request-------\n");
    strcat(buf, "\n");
    fflush(stdout);
    fputs(buf, stderr);
    fprintf(stderr, "----------------------------\n");

}
//display response message
void print_response(char *response) {
    char buf[MAXLINE];
    char *token;
    strcpy(buf, response);
    token = strtok(buf, " ");
    token = strtok(NULL, "\r");
    sprintf(buf, "%s\n", token);
    printf("<-- response\n");
    Fputs(buf, stdout);
    printf("\n");

}

//display response message
void print_response2(char *response, char *w1, char *w5) {
    int rp = 0;
    char *who_debug;
    if (!strcmp(w1, "200")) {
        rp = 1;
        printf("\n");
    }

    if (!strcmp(w1, "298")) {
        rp = 1;
        printf("\n");
    }

    if (!strcmp(w1, "210")) {
        rp = 1;
        who_debug = strtok(response, "\n");
        who_debug = strtok(NULL, "\r");
        sprintf(response, "ID LIST\n%s\n", who_debug);

        printf("<-- response\n");
        fputs(response, stdout);
        printf("\n");

    }

    char *msg;
    if (!strcmp(w1, "299")) {
        rp = 1;
        msg = strtok(response, "\n");
        msg = strtok(NULL, "\n");
        msg = strtok(NULL, "\r");
        sprintf(response, "<---- %s :  %s\n", w5, msg);
        fputs(response, stdout);
    }

    if (rp == 0)
        print_response(response);
}

// display debug response message
void debug_response(char *response) {
    char buf[MAXLINE];
    //char *token;
    strcpy(buf, response);
    fprintf(stderr, "----------debug response-------\n");
    strcat(buf, "\n");
    fflush(stdout);
    fputs(buf, stderr);
    //fflush(stderr);
    fprintf(stderr, "-------------------------------\n");

}
